#ifndef __SF_I2C_H_
#define __SF_I2C_H_

/* =========================== 用户配置 =========================== */
// 注意事项： 0-9：代表I2C接口ID号 0（%10 以此类推），并且一组I2C可能延时时间不同，所以0-9计算单独的时间
#include "main.h"
#include "gpio.h"
#include "System/DEBUG/debug.h"
#include "System/DELAY/delay.h"

#define SOFT_I2C_NUM 1           /* 软件I2C接口数量 */
#define SOFT_I2C_GROUP_MAX_NUM 1 /* 每组软件I2C接口最大数量 */

static const GPIO_TypeDef *sda_port[SOFT_I2C_NUM] = {GPIOB, };
static const uint16_t sda_pin[SOFT_I2C_NUM] = {GPIO_PIN_9, };

static const GPIO_TypeDef *scl_port[SOFT_I2C_NUM] = {GPIOB, };
static const uint16_t scl_pin[SOFT_I2C_NUM] = {GPIO_PIN_8, };

static const uint8_t i2c_delay_time[SOFT_I2C_NUM][SOFT_I2C_GROUP_MAX_NUM] = {{10},}; /* 软件I2C延时时间 */

#define I2C_LOG(...) debug_printf(__VA_ARGS__)

static inline void I2C_DELAY_US(uint8_t i2c_id) /* 软件I2C延时函数 */
{
    delay_us(i2c_delay_time[i2c_id / 10][i2c_id % 10]);
}

static inline void SDA_SET(uint8_t i2c_id, uint8_t state) /* 用户SDA引脚设置 */
{
    HAL_GPIO_WritePin((GPIO_TypeDef *)sda_port[i2c_id / 10], sda_pin[i2c_id / 10], state ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

static inline uint8_t SDA_READ(uint8_t i2c_id) /* 用户SDA引脚读取 */
{
    return HAL_GPIO_ReadPin((GPIO_TypeDef *)sda_port[i2c_id / 10], sda_pin[i2c_id / 10]) ? 1 : 0;
}

static inline void SCL_SET(uint8_t i2c_id, uint8_t state) /* 用户SCL引脚设置 */
{
    HAL_GPIO_WritePin((GPIO_TypeDef *)scl_port[i2c_id / 10], scl_pin[i2c_id / 10], state ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

static inline void SDA_OUT(uint8_t i2c_id) /* 用户SDA引脚设置为输出模式 */
{
}

static inline void SDA_IN(uint8_t i2c_id) /* 用户SDA引脚设置为输入模式 */
{
}

/* =========================== 外部声明 =========================== */

#include "stdint.h"

/**
 * @brief       初始化软件I2C
 * @param       i2c_id: I2C接口ID号
 * @retval      无
 */
void soft_i2c_init(uint8_t i2c_id);

/**
 * @brief       产生I2C起始信号
 * @param       i2c_id: I2C接口ID号
 * @retval      无
 */
void i2c_start(uint8_t i2c_id);

/**
 * @brief       产生I2C停止信号
 * @param       i2c_id: I2C接口ID号
 * @retval      无
 */
void i2c_stop(uint8_t i2c_id);

/**
 * @brief       等待应答信号到来
 * @param       i2c_id: I2C接口ID号
 * @retval      1，接收应答失败
 *              0，接收应答成功
 */
uint8_t i2c_wait_ack(uint8_t i2c_id);

/**
 * @brief       产生ACK应答
 * @param       i2c_id: I2C接口ID号
 * @retval      无
 */
void i2c_ack(uint8_t i2c_id);

/**
 * @brief       不产生ACK应答
 * @param       i2c_id: I2C接口ID号
 * @retval      无
 */
void i2c_nack(uint8_t i2c_id);

/**
 * @brief       I2C发送一个字节
 * @param       i2c_id: I2C接口ID号
 * @param       data: 要发送的数据
 * @retval      无
 */
void i2c_send_byte(uint8_t i2c_id, uint8_t data);

/**
 * @brief       I2C读取一个字节
 * @param       i2c_id: I2C接口ID号
 * @param       ack:  ack=1时，发送ack; ack=0时，发送nack
 * @retval      接收到的数据
 */
uint8_t i2c_read_byte(uint8_t i2c_id, uint8_t ack);

/**
 * @brief       软件I2C连续写数据
 * @param       i2c_id: I2C接口ID号
 * @param       salve_adress: 从设备地址
 * @param       reg_address: 寄存器地址
 * @param       data: 存储读取数据的缓冲区
 * @param       len: 要读取的数据长度
 * @retval      0，读取成功；1，读取失败
 */
uint8_t soft_i2c_write_data(uint8_t i2c_id, uint8_t slave_addr, uint8_t reg_address, const uint8_t *data, uint8_t len);

/**
 * @brief       软件I2C连续读数据
 * @param       i2c_id: I2C接口ID号
 * @param       salve_adress: 从设备地址
 * @param       reg_address: 寄存器地址
 * @param       data: 存储读取数据的缓冲区
 * @param       len: 要读取的数据长度
 * @retval      0，读取成功；1，读取失败
 */
uint8_t soft_i2c_read_data(uint8_t i2c_id, uint8_t slave_addr, uint8_t reg_address, uint8_t *data, uint8_t len);

/**
 * @brief       直接读 N 字节序列（无寄存器地址阶段）
 * @param       i2c_id: I2C接口ID号
 * @param       salve_adress: 从设备地址
 * @param       data: 存储读取数据的缓冲区
 * @param       len: 要读取的数据长度
 * @retval      0，读取成功；1，读取失败
 */
uint8_t soft_i2c_read_seq(uint8_t i2c_id, uint8_t slave_addr, uint8_t *data, uint8_t len);

#endif
